package cn.qianxun.meta.common.log.changeField.util;

import cn.qianxun.meta.common.core.utils.StringUtils;
import cn.qianxun.meta.common.log.changeField.annotation.CompareField;
import cn.qianxun.meta.common.core.constant.Constants;
import cn.qianxun.meta.common.log.changeField.vo.ChangeFieldValueVO;
import cn.qianxun.meta.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @Author fuzhilin
 * @Date 2023/9/5 10:07
 * @Description
 */
@Slf4j
public class ObjectComparatorUtil {
    /**
     * 字段变化值
     *
     * @param objId    对象Id
     * @param module   所属模块
     * @param operator 操作人
     * @param oldObj   旧对象
     * @param newObj   新对象
     * @return List<ChangeFieldValueVO>
     */
    public static List<ChangeFieldValueVO> compare(String objId, String module, String operator, Object oldObj, Object newObj) {
        List<ChangeFieldValueVO> fieldValueList = new ArrayList<>();
        try {
            // 获取所有字段
            Field[] fields = oldObj.getClass().getDeclaredFields();
            Field[] newFields = newObj.getClass().getDeclaredFields();
            // 遍历所有字段
            for (Field field : fields) {
                // 如果字段被 @CompareField 注解标注
                if (field.isAnnotationPresent(CompareField.class)) {
                    // 获取字段的中文名
                    String fieldName = field.getAnnotation(CompareField.class).value();
                    // 设置字段可访问
                    field.setAccessible(true);
                    // 获取字段的旧值和新值
                    Object oldValue = field.get(oldObj);
                    Field declaredField = newObj.getClass().getDeclaredField(field.getName());
                    declaredField.setAccessible(true);
                    Object newValue = declaredField.get(newObj);
                    // 如果值不相等
                    if (!Objects.equals(oldValue, newValue)) {
                        ChangeFieldValueVO fieldValueVO = new ChangeFieldValueVO();
                        // 将字段名和值添加到结果中
                        fieldValueVO.setObjId(objId);
                        fieldValueVO.setModule(module);
                        fieldValueVO.setOperator(operator);
                        fieldValueVO.setFiledName(fieldName);
                        String dictType = field.getAnnotation(CompareField.class).dictType();
                        String customType = field.getAnnotation(CompareField.class).customType();
                        if (StringUtils.isNotEmpty(dictType)) {
                            String oldValueDict = RedisUtils.getCacheObject(Constants.SYS_DICT_LABEL_KEY + dictType + ":" + oldValue);
                            String newValueDict = RedisUtils.getCacheObject(Constants.SYS_DICT_LABEL_KEY + dictType + ":" + newValue);
                            fieldValueVO.setOldValue(oldValueDict);
                            fieldValueVO.setNewValue(newValueDict);
                        }else if (StringUtils.isNotEmpty(customType)) {
                            Map<String, String> customTypeMap = stringToMap(customType);
                            if (!CollectionUtils.isEmpty(customTypeMap)) {
                                fieldValueVO.setOldValue(customTypeMap.get((String) oldValue));
                                fieldValueVO.setNewValue(customTypeMap.get((String) newValue));
                            }
                        } else {
                            fieldValueVO.setOldValue(oldValue);
                            fieldValueVO.setNewValue(newValue);
                        }

                        fieldValueVO.setOperationTime(new Date());
                        fieldValueList.add(fieldValueVO);
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取字段值变更失败");
            e.printStackTrace();
        }
        return fieldValueList;
    }


    /**
     * 根据#将字符串转换成map
     *
     * @param input input
     * @return Map
     */
    public static Map<String, String> stringToMap(String input) {
        Map<String, String> map = new HashMap<>();
        // 按 "#" 分割字符串得到键值对数组
        try {
            String[] keyValuePairs = input.split("#");
            for (String pair : keyValuePairs) {
                // 按 ":" 分割键值对
                String[] keyValue = pair.split(":");
                // 获取键和值
                String key = keyValue[0];
                String value = keyValue[1];
                // 添加到 Map 中
                map.put(key, value);
            }
        } catch (Exception e) {
            log.error("根据#将字符串转换成map失败" + e.getMessage());
            return map;
        }
        return map;
    }
}
